package net.sareweb.acab.actions.travel;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.event.ActionEvent;

import net.sareweb.acab.components.util.TravelCreationData;
import net.sareweb.acab.entity.City;
import net.sareweb.acab.entity.Country;
import net.sareweb.acab.entity.Seat;
import net.sareweb.acab.entity.State;
import net.sareweb.acab.entity.Travel;
import net.sareweb.acab.entity.manager.CityManager;
import net.sareweb.acab.entity.manager.CountryManager;
import net.sareweb.acab.entity.manager.SeatManager;
import net.sareweb.acab.entity.manager.StateManager;
import net.sareweb.acab.entity.manager.TravelManager;
import net.sareweb.acab.entity.manager.UserManager;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.remoting.WebRemote;
import org.jboss.seam.core.Events;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;

@Name("createTravelBean")
@Scope(ScopeType.CONVERSATION)
public class CreateTravelBean {
	
	@Logger
	private Log log;
	
	@Out
	TravelCreationData travelCreationData;
	
	@In(create=true)
	UserManager userManager;

	@In(create=true)
	CountryManager countryManager;
	@In(create=true)
	StateManager stateManager;
	@In(create=true)
	CityManager cityManager;
	@In(create=true)
	TravelManager travelManager;
	@In(create=true)
	SeatManager seatManager;
	
	@In 
	Credentials credentials;
	
	
	
	public String chooseNameSeatsAndLocationTypeAction(){
		log.debug("Travel name: {0}", travelCreationData.getTravelName());
		log.debug("sean amount: {0}", travelCreationData.getSeatAmount());
		log.debug("the way to choose location: {0}", travelCreationData.getLocationType());
		if(travelCreationData.getLocationType()==null)return "";
		
		else{
			/*At this point loading country,state and/or city list from DB if needed*/
			updateFromComboData();
			updateToComboData();
			
			if(travelCreationData.getLocationType().equals(TravelCreationData.LOCATIONTYPE_CITY))return "cityLocation";
			else if(travelCreationData.getLocationType().equals(TravelCreationData.LOCATIONTYPE_MAPS))return "gMapsLocation";
			else return "";
		}
	}
	
	public String chooseCoordsAction(){
		log.debug("(the way to choose location: {0})", travelCreationData.getLocationType());
		log.debug("from coords: {0},{1} to coords: {2},{3}", travelCreationData.getFromLat(), travelCreationData.getFromLon(), travelCreationData.getToLat(), travelCreationData.getToLon());
		return "choosePeriodType";
	}

	public String chooseCitiesAction(){
		log.debug("(the way to choose location: {0})", travelCreationData.getLocationType());
		log.debug("from city {0} to city {1}", travelCreationData.getFromCity(),travelCreationData.getToCity());
		return "choosePeriodType";
	}

	
	
	public String choosePeriodTypeAction(){
		log.debug("the way to choose period: {0}", travelCreationData.getPeriodType());
		return travelCreationData.getPeriodType();
	}
	
	public String selectSingleDateAction(){
		log.debug("selected date for travel: {0}", travelCreationData.getTravelDate1());
		return "summary";
	}
	
	public String selectMultiDateAction(){
		log.debug("selected date for travel from date {0} to date {1}", travelCreationData.getTravelDate1(), travelCreationData.getTravelDate2());
		return "summary";
	}
	
	public String saveTravelAction(){
		log.debug("Creating new travel ({0})", travelCreationData.getTravelName());
		Travel t = new Travel();
		t.setName(travelCreationData.getTravelName());
		t.setUser(userManager.findByLoginName(credentials.getUsername()));
		if(travelCreationData.getLocationType().equals("maps")){
			t.setFromLat(travelCreationData.getFromLat().floatValue());
			t.setFromLon(travelCreationData.getFromLon().floatValue());
			t.setToLat(travelCreationData.getToLat().floatValue());
			t.setToLon(travelCreationData.getToLon().floatValue());
			/*Calculate distance in KM between coords*/
			double d = Math.acos(
						(
						Math.sin(Math.toRadians(travelCreationData.getFromLat()))
						*
						Math.sin(Math.toRadians(travelCreationData.getToLat()))
						)
						+
						(
						Math.cos(Math.toRadians(travelCreationData.getFromLat()))
						*
						Math.cos(Math.toRadians(travelCreationData.getToLat()))
						*
						Math.cos(Math.toRadians(travelCreationData.getFromLon()) - Math.toRadians(travelCreationData.getToLon()))
						)
						
						
					);
			d = d * 6378;
			t.setDistance(new Float(d));
			
		}else if(travelCreationData.getLocationType().equals("city")){
			if(travelCreationData.getFromCity()!=null){
				City c = cityManager.find(travelCreationData.getFromCity());
				t.setCityByFromCity(c);
				t.setStateByFromState(c.getState());
				t.setCountryByFromCountry(c.getState().getCountry());
			}
			if(travelCreationData.getToCity()!=null){
				City c = cityManager.find(travelCreationData.getToCity());
				t.setCityByToCity(c);
				t.setStateByToState(c.getState());
				t.setCountryByToCountry(c.getState().getCountry());
			}
			
		}
		t.setCalculatedRate(0);
		t.setTravelState("FREE");/*TODO: define what are travel states*/
		t.setCreateDate(new Date());
		t.setCronExpression("");
		
		if(travelCreationData.getSelectedDays()!=null){
			for (int i = 0; i < travelCreationData.getSelectedDays().size(); i++) {
				String day = travelCreationData.getSelectedDays().get(i);
				if(day.equals("MON"))t.setMonday(true);
				if(day.equals("TUE"))t.setTuesday(true);
				if(day.equals("WED"))t.setWednesday(true);
				if(day.equals("THU"))t.setThursday(true);
				if(day.equals("FRI"))t.setFriday(true);
				if(day.equals("SAT"))t.setSaturday(true);
				if(day.equals("SUN"))t.setSunday(true);
			}
		}
		
		t.setBeginDate(travelCreationData.getTravelDate1());
		t.setEndDate(travelCreationData.getTravelDate2());
		if(travelCreationData.getPeriodType().equals(TravelCreationData.PERIODTYPE_SINGLE)){
			t.setSingleDay(true);
		}
		else{
			t.setSingleDay(false);
		}
		
		
		
		travelManager.save(t);
		
		createTravelSeats(t);
		Events.instance().raiseEvent("travelCreatedEvent");
		return "finish";
	}
	
	
	public void updateFromComboListener(ActionEvent event){
		log.debug("Updating FROM combos.", "");
		updateFromComboData();
	}
	
	public void updateToComboListener(ActionEvent event){
		log.debug("Updating TO combos.", "");
		updateToComboData();
	}

	
	@Begin
	public String start(){
		return "/acab/travel/CreateTravelBegin.xhtml";
	}
	
	@End
	public String end(){
		return "/home.xhtml";
	}
	
	@Factory(value="travelCreationData")
	public void instantiateCreateData(){
		if(this.travelCreationData==null){
			log.debug("Instantiating creation data container", "");
			this.travelCreationData= new TravelCreationData();
		}
	}
	
	
	@WebRemote
	public String updateFromPoint(Double lat, Double lng){
		travelCreationData.setFromLat(lat);
		travelCreationData.setFromLon(lng);
		return "(" + travelCreationData.getFromLat() + ","  + travelCreationData.getFromLon() + ")";
	}
	@WebRemote
	public String updateToPoint(Double lat, Double lng){
		travelCreationData.setToLat(lat);
		travelCreationData.setToLon(lng);
		return "(" + travelCreationData.getToLat() + ","  + travelCreationData.getToLon() + ")";
	}
	
	
	public void updateFromComboData(){
		if(travelCreationData.getFromCountries()==null || travelCreationData.getFromCountries().size()==0){
			List<Country> fromCos = countryManager.findAll();
			travelCreationData.setFromCountries(fromCos);
		}
		/*if selected  fromCountry -->load its states*/
		if(travelCreationData.getFromCountry()!=null){
			List<State> fromSts = stateManager.findByCountry(travelCreationData.getFromCountry());
			travelCreationData.setFromStates(fromSts);
			if(travelCreationData.getFromState()!=null){
				List<City> fromCts = cityManager.findByState(travelCreationData.getFromState());
				travelCreationData.setFromCities(fromCts);
			}
			else{//if no state selected, deselect city and empty its list
				travelCreationData.setFromCity(null);
				travelCreationData.setFromCities(new ArrayList<City>());
			}
		}
		else{//if no contry selected, deselect state and city and empty their lists
			travelCreationData.setFromState(null);
			travelCreationData.setFromCity(null);
			travelCreationData.setFromStates(new ArrayList<State>());
			travelCreationData.setFromCities(new ArrayList<City>());
		}
	}
	
	public void updateToComboData(){
		if(travelCreationData.getToCountries()==null || travelCreationData.getToCountries().size()==0){
			List<Country> toCos = countryManager.findAll();
			travelCreationData.setToCountries(toCos);
		}
		/*if selected  toCountry -->load its states*/
		if(travelCreationData.getToCountry()!=null){
			List<State> toSts = stateManager.findByCountry(travelCreationData.getToCountry());
			travelCreationData.setToStates(toSts);
			if(travelCreationData.getToState()!=null){
				List<City> toCts = cityManager.findByState(travelCreationData.getToState());
				travelCreationData.setToCities(toCts);
			}
			else{//if no state selected, deselect city and empty its list
				travelCreationData.setToCity(null);
				travelCreationData.setToCities(new ArrayList<City>());
			}
		}
		else{//if no contry selected, deselect state and city and empty their lists
			travelCreationData.setToState(null);
			travelCreationData.setToCity(null);
			travelCreationData.setToStates(new ArrayList<State>());
			travelCreationData.setToCities(new ArrayList<City>());
		}
	}
	
	private void createTravelSeats(Travel t){

		for (int i = 0; i < travelCreationData.getSeatAmount(); i++) {
			Seat s = new Seat();
			s.setSeatNumber(i+1);
			s.setState(SeatManager.SEAT_STATE_FREE);
			s.setTravel(t);
			seatManager.save(s);
	
		}

	}

}
